package cn.pugle.base.thread.forkjoin;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;

/**
 * @author tzp
 * @since 2020/10/27
 */
public class FJCounter1 {
    static class Counter2 extends ForkJoinTask<Integer> {
        @Override
        public Integer getRawResult() {
            return null;
        }

        @Override
        protected void setRawResult(Integer value) {

        }

        @Override
        protected boolean exec() {
            return false;
        }
    }

    /**
     * 找到数组中大于50的元素的个数;
     * 长度<=10的时候直接运算, 否则fork
     */
    static class Counter1 extends RecursiveTask<Integer> {
        static int maxComputeLength = 10;
        int[] ar;
        int start;
        int end;

        public Counter1(int[] ar, int start, int end/*exclude*/) {
            this.ar = ar;
            this.start = start;
            this.end = end;
        }

        @Override
        protected Integer compute() {
            String tname = Thread.currentThread().getName();
            if (end - start <= maxComputeLength) {
//                if (Math.random() < 10) {//抛出异常不就崩了么
//                    throw new RuntimeException();
//                }
                System.out.println(tname + "开始实际计算");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                }
                int cnt = 0;
                for (int i = start; i < end; i++) {
                    if (ar[i] > 50) cnt++;
                }
                System.out.println(tname + "结束实际计算");
                return cnt;
            } else {
                //直接分够得了, 不写二分再二分了
                System.out.println(tname + "开始fork");
                int segmentStart = start;
                int segmentEnd = start + maxComputeLength;
                List<Counter1> tasks = new ArrayList<>();
                while (segmentStart < end) {
                    Counter1 subTask = new Counter1(ar, segmentStart, Math.min(segmentEnd, end));
                    subTask.fork();
                    tasks.add(subTask);
                    segmentStart += maxComputeLength;
                    segmentEnd += maxComputeLength;
                }
                System.out.println(tname + "等待fork结果");
                //invokeAll(tasks);//相当于挨个fork, 挨个join
                int sum = 0;
                for (Counter1 task : tasks) {
                    Integer join = task.join();
                    sum += join;
                }
                System.out.println(tname + "汇总返回结果");
                return sum;
            }
        }

    }

    public static void main(String[] args) {
        int[] ar = new int[39];
        Random rand = new Random();
        for (int i = 0; i < 39; i++) {
            ar[i] = rand.nextInt(100);
        }

        {
            Counter1 task = new Counter1(ar, 0, 39);
            ForkJoinPool newPool = (ForkJoinPool) Executors.newWorkStealingPool(2);
            newPool.submit(task);
            //
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Counter1 task = new Counter1(ar, 0, 39);
                    newPool.submit(task);
                }
            }, "anotherT").start();
            //
            System.out.println("-------------");
            try {
                Thread.sleep(4000);//加入这行, 就不会出现main帮忙干活的情况了
                Integer integer = task.get();
                System.out.println(integer);
            } catch (InterruptedException e) {
                System.out.println(e.getMessage());
            } catch (ExecutionException e) {
                System.out.println(e.getMessage());
            }
            System.out.println("-------------");
        }
    }
}
